<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>AI Chatroom</title>
    <style>
        * {
            margin: 0;
            padding: 0;
            box-sizing: border-box;
        }

        :root {
            --bg: #0b0f19;
            --panel: #0f172a;
            --panel-2: #0b1220;
            --border: #1f2937;
            --text: #e5e7eb;
            --text-muted: #9ca3af;
            --primary: #22c55e;
            --primary-2: #16a34a;
            --danger: #ef4444;
            --yellow: #f59e0b;
            --bubble-user: #1f2937;
            --bubble-ai: #0b1220;
            --shadow: 0 10px 30px rgba(0,0,0,0.35);
        }

        body {
            font-family: ui-sans-serif, system-ui, -apple-system, Segoe UI, Roboto, Helvetica, Arial;
            background: var(--bg);
            color: var(--text);
            height: 100vh;
            overflow: hidden;
        }

        .layout {
            display: grid;
            grid-template-columns: 280px 1fr;
            height: 100vh;
        }

        /* Sidebar */
        .sidebar {
            background: linear-gradient(180deg, var(--panel) 0%, var(--panel-2) 100%);
            border-right: 1px solid var(--border);
            padding: 16px;
            display: flex;
            flex-direction: column;
            gap: 12px;
        }

        .brand {
            display: flex;
            align-items: center;
            gap: 10px;
            padding: 10px 12px;
            border: 1px solid var(--border);
            border-radius: 10px;
            background: rgba(255,255,255,0.02);
        }
        .brand .dot {
            width: 10px; height: 10px; border-radius: 50%; background: var(--primary);
            box-shadow: 0 0 10px var(--primary);
        }
        .brand strong { letter-spacing: .3px; }

        .sidebar-actions {
            display: flex; gap: 8px;
        }
        .btn {
            background: #111827;
            color: var(--text);
            border: 1px solid var(--border);
            padding: 8px 10px;
            border-radius: 8px;
            cursor: pointer;
            transition: .15s ease;
        }
        .btn:hover { background: #0b1220; }
        .btn.primary { background: var(--primary); border-color: var(--primary-2); color: #051b0d; font-weight: 600; }
        .btn.primary:hover { filter: brightness(1.05); }

        .conv-list { flex: 1; overflow: auto; padding-right: 4px; }
        .conv-item {
            display: flex; align-items: center; gap: 8px;
            padding: 10px 12px; border: 1px solid var(--border); border-radius: 10px;
            margin-bottom: 8px; background: rgba(255,255,255,0.02);
            cursor: pointer; transition: .15s ease;
        }
        .conv-item.active { border-color: var(--primary-2); background: rgba(34,197,94,0.06); }
        .conv-item:hover { background: rgba(255,255,255,0.04); }
        .conv-title { flex: 1; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
        .conv-del { color: var(--text-muted); }

        /* Main */
        .main {
            display: grid; grid-template-rows: auto 1fr auto; height: 100vh; background: radial-gradient(1200px 600px at 20% -20%, rgba(34,197,94,0.08), transparent 60%),
            radial-gradient(800px 500px at 100% 0%, rgba(59,130,246,0.06), transparent 60%);
        }

        .toolbar {
            display: flex; align-items: center; justify-content: space-between;
            padding: 12px 16px; border-bottom: 1px solid var(--border); background: var(--panel);
        }
        .select, .input { background: #0b1220; color: var(--text); border: 1px solid var(--border); border-radius: 8px; }
        .select { padding: 10px 12px; }

        .userbox { display: flex; align-items: center; gap: 8px; }
        .userbox .status { font-size: 12px; color: var(--text-muted); }

        .chat {
            overflow: auto; padding: 20px 20px 120px; scroll-behavior: smooth;
        }
        .msg { display: grid; grid-template-columns: 42px 1fr; gap: 12px; margin: 8px 0; }
        .avatar { width: 42px; height: 42px; border-radius: 50%; border: 1px solid var(--border); background: #0b1220; display: grid; place-items: center; font-weight: 700; color: var(--text-muted); }
        .bubble { border: 1px solid var(--border); border-radius: 12px; padding: 12px 14px; box-shadow: var(--shadow); line-height: 1.6; }
        .user .bubble { background: var(--bubble-user); }
        .ai .bubble { background: var(--bubble-ai); }
        .muted { color: var(--text-muted); font-size: 12px; margin-top: 6px; }

        .composer {
            position: sticky; bottom: 0; left: 0; right: 0; background: linear-gradient(180deg, transparent, var(--panel));
            padding: 16px; border-top: 1px solid var(--border);
        }
        .composer-inner { display: flex; gap: 10px; background: var(--panel); border: 1px solid var(--border); border-radius: 14px; padding: 10px; }
        textarea.input { flex: 1; resize: none; min-height: 52px; max-height: 180px; padding: 10px 12px; outline: none; }
        .send { min-width: 100px; }

        .login-modal {
            position: fixed; inset: 0; background: rgba(0,0,0,.6); display: none; align-items: center; justify-content: center;
        }
        .login-card { width: 420px; max-width: calc(100% - 32px); background: var(--panel); border: 1px solid var(--border); border-radius: 12px; padding: 16px; box-shadow: var(--shadow); }
        .field { display: grid; gap: 6px; margin: 10px 0; }
        .field label { color: var(--text-muted); font-size: 13px; }
        .field .input { padding: 10px 12px; }
        .row { display: flex; gap: 8px; justify-content: flex-end; margin-top: 6px; }
        .error { color: var(--danger); font-size: 13px; margin-top: 6px; }

        @media (max-width: 960px) {
            .layout { grid-template-columns: 1fr; }
            .sidebar { display: none; }
            .toolbar { flex-wrap: wrap; gap: 8px; }
            .composer { padding: 12px; }
            .composer-inner { flex-direction: column; }
            textarea.input { min-height: 80px; font-size: 16px; }
            .send { width: 100%; padding: 12px; }
        }
    </style>
    <meta name="color-scheme" content="dark light">
    <meta name="theme-color" content="#0b0f19">
    <link rel="icon" href="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100'%3E%3Ccircle cx='50' cy='50' r='42' fill='%2322c55e'/%3E%3Ctext x='50' y='60' text-anchor='middle' font-size='54' fill='white' font-family='Arial'%3EAI%3C/text%3E%3C/svg%3E">
</head>
<body>
    <div class="layout">
        <aside class="sidebar">
            <div class="brand"><div class="dot"></div><strong>AI Chatroom</strong></div>
            <div class="sidebar-actions">
                <button class="btn primary" id="newConvBtn">新建会话</button>
                <button class="btn" id="clearAllBtn">清空</button>
            </div>
            <div id="convList" class="conv-list"></div>
            <div class="userbox">
                <div style="flex:1">
                    <div style="font-size:14px">账户：<span id="userName">未登录</span></div>
                    <div class="status" id="loginStatus">需要登录以调用接口</div>
                </div>
                <a class="btn" href="vector.html">向量库</a>
                <a class="btn" id="loginLink" href="login.html?redirect=index.html">登录/注册</a>
                <button class="btn" id="logoutBtn" style="display:none">退出</button>
            </div>
        </aside>
        <main class="main">
            <div class="toolbar">
                <div style="display:flex; gap:8px; align-items:center">
                    <label for="model" class="status">模型</label>
                    <select id="model" class="select">
                        <option value="deepseek">Deepseek V3</option>
                        <option value="qwen">Qwen Plus</option>
                    </select>
                </div>
                <div class="status">不支持流式（后端返回整段）</div>
            </div>
            <div id="chat" class="chat"></div>
            <div class="composer">
                <div class="composer-inner">
                    <textarea id="input" class="input" placeholder="输入消息，Enter 发送，Shift+Enter 换行"></textarea>
                    <button id="send" class="btn primary send">发送</button>
                </div>
            </div>
        </main>
    </div>

    

    <script>
        const baseUrl = '/bldp';
        const chatEl = document.getElementById('chat');
        const inputEl = document.getElementById('input');
        const sendBtn = document.getElementById('send');
        const modelEl = document.getElementById('model');
        const convListEl = document.getElementById('convList');
        const userNameEl = document.getElementById('userName');
        const loginStatusEl = document.getElementById('loginStatus');
        const loginLink = document.getElementById('loginLink');
        const logoutBtn = document.getElementById('logoutBtn');

        let conversations = loadConversations();
        let currentConvId = ensureCurrentConversation();

        // --- Conversation Storage ---
        function loadConversations() {
            try { return JSON.parse(localStorage.getItem('conversations') || '{}'); } catch { return {}; }
        }
        function saveConversations() {
            localStorage.setItem('conversations', JSON.stringify(conversations));
        }
        function ensureCurrentConversation() {
            const cid = localStorage.getItem('currentConvId');
            if (cid && conversations[cid]) return cid;
            const newId = 'c' + Date.now();
            conversations[newId] = { id: newId, title: '新会话', model: modelEl.value, messages: [] };
            saveConversations();
            localStorage.setItem('currentConvId', newId);
            return newId;
        }
        function setCurrentConversation(id) {
            currentConvId = id; localStorage.setItem('currentConvId', id); renderConversations(); renderChat();
        }

        // --- Auth ---
        function getToken() { return localStorage.getItem('token') || ''; }
        function getUser() { return localStorage.getItem('username') || '未登录'; }
        function setAuth(username, token) {
            localStorage.setItem('username', username);
            localStorage.setItem('token', token);
            updateAuthUI();
        }
        function clearAuth() {
            localStorage.removeItem('username');
            localStorage.removeItem('token');
            updateAuthUI();
        }
        function updateAuthUI() {
            const token = getToken();
            const loggedIn = !!token;
            userNameEl.textContent = getUser();
            loginStatusEl.textContent = loggedIn ? '已登录，可调用受保护接口' : '需要登录以调用接口';
            if (loginLink) loginLink.style.display = loggedIn ? 'none' : '';
            logoutBtn.style.display = loggedIn ? '' : 'none';
        }

        // --- UI Renders ---
        function renderConversations() {
            convListEl.innerHTML = '';
            Object.values(conversations).sort((a,b)=>b.id.localeCompare(a.id)).forEach(conv => {
                const div = document.createElement('div');
                div.className = 'conv-item' + (conv.id === currentConvId ? ' active' : '');
                div.innerHTML = `<span class="conv-title">${conv.title || '未命名会话'}</span>`;
                const del = document.createElement('button'); del.className = 'btn conv-del'; del.textContent = '删';
                del.onclick = (e)=>{ e.stopPropagation(); delete conversations[conv.id]; saveConversations(); if (currentConvId===conv.id) currentConvId = ensureCurrentConversation(); renderConversations(); renderChat(); };
                div.appendChild(del);
                div.onclick = ()=> setCurrentConversation(conv.id);
                convListEl.appendChild(div);
            });
        }
        function renderChat() {
            const conv = conversations[currentConvId]; if (!conv) return;
            chatEl.innerHTML = '';
            conv.messages.forEach(m => {
                const row = document.createElement('div'); row.className = 'msg ' + (m.role === 'user' ? 'user' : 'ai');
                row.innerHTML = `
                    <div class="avatar">${m.role === 'user' ? 'U' : 'AI'}</div>
                    <div>
                        <div class="bubble">${escapeHtml(m.content).replace(/\n/g,'<br>')}</div>
                        <div class="muted">${new Date(m.ts).toLocaleString()}</div>
                    </div>`;
                chatEl.appendChild(row);
            });
            chatEl.scrollTop = chatEl.scrollHeight;
            // 自动标题
            if (!conversations[currentConvId].title && conv.messages.length>0) {
                conversations[currentConvId].title = conv.messages[0].content.slice(0, 20);
                saveConversations(); renderConversations();
            }
        }

        function escapeHtml(s){ return s.replace(/[&<>"']/g, c=>({"&":"&amp;","<":"&lt;",">":"&gt;","\"":"&quot;","'":"&#39;"}[c])); }

        // --- Send Logic ---
        async function sendMessage() {
            const text = inputEl.value.trim(); if (!text) return;
            const token = getToken(); if (!token) { openLogin(); return; }
            const model = modelEl.value;

            appendMessage('user', text);
            inputEl.value = '';
            const thinkingId = appendMessage('ai', '思考中...');

            try {
                const endpoint = model === 'deepseek' ? '/chatdp' : '/chatqw';
                const isPost = model === 'deepseek';
                const url = `${baseUrl}${endpoint}?msg=${encodeURIComponent(text)}`;

                const resp = await fetch(url, {
                    method: isPost ? 'POST' : 'GET',
                    headers: { 'token': token }
                });

                if (!resp.ok) throw new Error(`HTTP ${resp.status}`);
                const result = await resp.text();
                replaceMessage(thinkingId, 'ai', result || '(空响应)');
            } catch (e) {
                replaceMessage(thinkingId, 'ai', `请求失败：${e.message}`);
            }
        }

        function appendMessage(role, content) {
            const msg = { id: 'm'+Date.now()+Math.random().toString(16).slice(2), role, content, ts: Date.now() };
            conversations[currentConvId].messages.push(msg);
            saveConversations(); renderChat();
            return msg.id;
        }
        function replaceMessage(id, role, content) {
            const list = conversations[currentConvId].messages;
            const idx = list.findIndex(m=>m.id===id); if (idx>=0) { list[idx].role = role; list[idx].content = content; list[idx].ts = Date.now(); }
            saveConversations(); renderChat();
        }

        // --- Login ---
        // 移除内置登录/注册逻辑，改为独立页面

        // --- Events ---
        sendBtn.addEventListener('click', sendMessage);
        inputEl.addEventListener('keydown', (e)=>{
            if (e.key === 'Enter' && !e.shiftKey) { e.preventDefault(); sendMessage(); }
        });
        document.getElementById('newConvBtn').addEventListener('click', ()=>{
            const id = 'c'+Date.now(); conversations[id] = { id, title: '新会话', model: modelEl.value, messages: [] }; saveConversations(); setCurrentConversation(id);
        });
        document.getElementById('clearAllBtn').addEventListener('click', ()=>{
            if (confirm('确定清空所有本地会话？')) { conversations = {}; saveConversations(); setCurrentConversation(ensureCurrentConversation()); }
        });
        logoutBtn.addEventListener('click', clearAuth);
        
        // 未登录强制跳转到登录页
        (function guard(){ if(!getToken()){ location.href = 'login.html?redirect=' + encodeURIComponent('index.html'); } })();

        // --- Init ---
        updateAuthUI();
        renderConversations();
        renderChat();
    </script>
</body>
</html>
